<?php

/**
 * Request wrapper.
 * @package Nina
 * @author John Main <john@thedaddy.org>
 */


/**
 * Request class.
 */
class Nina_Request
{
	/**
	 * Constant for a request which is GET.
	 */
	const GET = "GET";
	/**
	 * Constant for a request which is POST.
	 */
	const POST = "POST";
	/**
	 * Constant for a request which is FILES.
	 */
	const FILES = "FILES";
	/**
	 * Constant for a request which is ANYthing.
	 */
	const ALL = "ALL";

	protected $additional = array();

	/**
	 * Constructor
	 */
	public function __construct() {
	}

	/**
	 * Get the method which was sent with the HTTP request.
	 * This returns one of the constants Nina_Request::GET or POST.
	 * @return string
	 */
	public function getRequestMethod() {
		return isset($_SERVER["REQUEST_METHOD"]) ? $_SERVER["REQUEST_METHOD"] : null;
	}

	/**
	 * Check if this request has an AJAX flag
	 * @return boolean
	 */
	public function isAjax() {
		return $this->getParameter('ajax') ? true : false;
	}

	/**
	 * Check if a particular attribute has been stored here.
	 * @param string $key Attribute key
	 * @return boolean
	 */
	public function hasAttribute($key) {
		return array_key_exists($key, $this->attributes);
	}

	/**
	 * Check if any attributes are present in the request.
	 * @return boolean
	 */
	public function hasAttributes() {
		return !empty($this->attributes);
	}

	/**
	 * Check if a given parameter was passed along with this request.
	 * The values come from the HTTP protocol.
	 * @param string $key Key name for the value
	 * @param string [$type=self::ALL] constant from Nina_Request::GET, POST, FILES or ALL (defaults to ALL)
	 * @return boolean
	 */
	public function hasParameter($key, $type=self::ALL) {
		switch ($type) {
			case self::POST:
				return isset($_POST[$key]);
			case self::GET:
				return isset($_GET[$key]);
			case self::FILES:
				return isset($_FILES[$key]);
			case self::ALL: default:
				return (isset($_REQUEST[$key]) || isset($this->additional[$key]));
		}
	}

	/**
	 * Set a value so it looks as if it was sent as part of the HTTP Request.
	 * @param string $key Key name for the value
	 * @param mixed $value The value
	 * @param string [$type=self::ALL] constant from Nina_Request::GET, POST, FILES or ALL (defaults to ALL)
	 */
	public function setParameter($var, $value, $type=self::ALL) {

		switch ($type) {
			case self::POST:
				$_POST[$var] = $value;
				break;
			case self::GET:
				$_GET[$var] = $value;
				break;
			case self::FILES:
				$_FILES[$var] = $value;
				break;
			case self::ALL: default:
				$this->additional[$var] = $value;
				break;
		}
	}

	/**
	 * Retrieve a given parameter passed along with this request.
	 * The values come from the HTTP protocol.
	 * @param string $key Key name for the value
	 * @param string [$type=self::ALL] constant from Nina_Request::GET, POST, FILES or ALL (defaults to ALL)
	 * @return mixed|false
	 */
	public function getParameter($key, $type=self::ALL) {
		if ($this->hasParameter($key, $type)) {
			switch ($type) {
				case self::POST:
					return $_POST[$key];
				case self::GET:
					return $_GET[$key];
				case self::FILES:
					return $_FILES[$key];
				case self::ALL: default:
					if(isset($_REQUEST[$key]))
						return $_REQUEST[$key];
					elseif(isset($this->additional[$key]))
						return $this->additional[$key];
			}
		}

		return false;
	}

	/**
	 * Retrieve a given parameter passed along with this request and sanitise it.
	 * @param string $key Key name for the value
	 * @param string [$type=self::ALL] constant from Nina_Request::GET, POST, FILES or ALL (defaults to ALL)
	 * @return string
	 */
	public function getSanitisedParameter($key, $type=self::ALL) {
		return Nina_String::doSanitise($this->getParameter($key, $type));
	}

	/**
	 * Retrieve all parameters passed along with this request.
	 * The values come from the HTTP protocol.
	 * @param string [$type=self::ALL] constant from Nina_Request::GET, POST, FILES or ALL (defaults to ALL)
	 * @return array
	 */
	public function getParameters($type=self::ALL) {
		switch ($type) {
			case self::POST:
				return $_POST;
			case self::GET:
				return $_GET;
			case self::FILES:
				return $_FILES;
			case self::ALL: default:
				return $_REQUEST;
		}
	}

	/**
	 * Clears all parameters passed along with this request.
	 * The values come from the HTTP protocol.
	 * @param string $type Constant from Nina_Request::GET, POST or FILES
	 */
	public function clearParameters($type) {
		switch ($type) {
			case self::POST:
				$_POST = array();
			case self::GET:
				$_GET = array();
			case self::FILES:
				$_FILES = array();
		}
	}

	/**
	 * Set a cookie
	 * @param string $key Key for the variable
	 * @param mixed $value The value
	 * @param integer [$expire=86400] Seconds until expiry
	 * @param string [$path='/'] Path
	 */
	public function setCookie($key, $value, $expire = 86400, $path = '/') {
		setcookie($key, $value, time() + $expire, $path);
	}

	/**
	 * Retrieve a given cookie passed along with this request.
	 * @param string $key Key name for the value
	 * @return mixed
	 */
	public function getCookie($key) {
		return array_key_exists($key, $_COOKIE) ? $_COOKIE[$key] : false;
	}


	/**
	 * Retrieve all cookies passed along with this request.
	 * @return array
	 */
	public function getCookies() {
		return $_COOKIE;
	}

	/**
	 * Get the remote IP address of this request.
	 * If $resolve_proxies is TRUE, the forwarded-for header will also be checked.
	 * The return value of this method may be an IPv6 or IPv4 address.
	 * This method returns false where no IP is present (on command line).
	 * @param boolean [$resolve_proxies=false] Resolve proxy hosts
	 * @return string
	 */
	public function getRemoteIp($resolve_proxies = false) {
		if (!isset($_SERVER["REMOTE_ADDR"])) {
			return false;
		}

		$remote_addr = $_SERVER["REMOTE_ADDR"];
		$bits = explode(",", $remote_addr);
		$remote_addr = trim(array_shift($bits));
		if ($resolve_proxies && !empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
			$forwarded_for = $_SERVER["HTTP_X_FORWARDED_FOR"];
			$bits = explode(",", $forwarded_for);
			$forwarded_for = trim(array_shift($bits));
			return $forwarded_for;
		}
		else
			return $remote_addr;
	}
}
